package demo.messaging.client.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.ListBox;

import demo.messaging.client.core.ClientManager;
import demo.messaging.client.core.IMessageEventListener;
import demo.messaging.client.core.MessageEvent;
import demo.messaging.client.core.MessageEvent.EnumMessageEventType;
import demo.messaging.common.ControlMessage;
import demo.messaging.common.EnumUserStatus;
import demo.messaging.common.ControlMessage.EnumControlType;
import demo.util_ui.client.ui.AbstractDialog;
import demo.util_ui.client.ui.UIFactory;

/**
 * UI used for listing users.
 * 
 * @author Prawee Sriplakich
 *
 */
public class MeettingUI extends AbstractDialog implements IMessageEventListener {

	/**
	 * List of users currently logged in the application.
	 */
	private final ListBox listUsers = new ListBox(true);

	private final Button inviteButton = new Button("Invite");

	private final Button logoutButton = new Button("Logout");

	private final OutgoingInvitationUI waitInviteResponseDialog = new OutgoingInvitationUI();

	private final IncomingInvitationUI inviteNotificationDialog = new IncomingInvitationUI();

	protected ListBox listGameChoices = new ListBox();

	public MeettingUI() {

		this.inviteButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(final ClickEvent event) {
				sendInvitation();
			}
		});
		this.inviteButton.setEnabled(false);

		this.logoutButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(final ClickEvent event) {
				logout();
			}
		});
		this.inviteButton.setEnabled(true);

		setText("You can invite a friend to join a game");

		this.listUsers.addChangeHandler(new ChangeHandler() {

			@Override
			public void onChange(final ChangeEvent event) {
				updateButtonEnable();

			}
		});

		this.listUsers.addStyleName("listUsers");
		this.listGameChoices.addStyleName("listGameChoices");

		getContentPanel().add(UIFactory.createLabel("Online users :", "label"),
				DockPanel.WEST);
		getContentPanel().add(this.listUsers, DockPanel.CENTER);

		getContentPanel().add(this.listGameChoices, DockPanel.EAST);
		getContentPanel().add(
				UIFactory.createLabel("Choice of games :", "label"),
				DockPanel.EAST);

		getBottomPanel().add(this.inviteButton, DockPanel.EAST);

		getBottomPanel().add(this.logoutButton, DockPanel.EAST);

	}

	public IncomingInvitationUI getInviteNotificationDialog() {
		return this.inviteNotificationDialog;
	}

	public ListBox getListGameChoices() {
		return this.listGameChoices;
	}

	public OutgoingInvitationUI getWaitInviteResponseDialog() {
		return this.waitInviteResponseDialog;
	}

	/**
	 * Send MessageInviteMessageSession
	 */
	private void logout() {

		Log.debug("UI: logout ");

		ClientManager.getClientManager().logout();

		Window.Location.assign("index.html");
	}

	/**
	 * Update list users and check for incoming invitations.
	 */
	@Override
	public void onMessageEvent(final MessageEvent event) {
		if (event.getType() == EnumMessageEventType.listUserUpdated) {

			updateListUsers();
		}
	}

	/**
	 * Send MessageInviteMessageSession
	 */
	private void sendInvitation() {
		String guest = this.listUsers.getValue(this.listUsers
				.getSelectedIndex());
		String game = this.listGameChoices.getValue(this.listGameChoices
				.getSelectedIndex());

		Log.debug("UI: sendInvitation to " + guest + " for " + game);

		final ControlMessage m = new ControlMessage(EnumControlType.invite);
		m.setDestination(guest);
		m.setGameChoice(game);

		String gameName = this.listGameChoices.getItemText(this.listGameChoices
				.getSelectedIndex());

		m.setText("Hi! Would you like to play " + gameName + " ?");

		ClientManager.getClientManager().sendInvitation(m);
	}

	protected void updateButtonEnable() {
		if (this.listUsers.getSelectedIndex() >= 0) {
			String guest = this.listUsers.getValue(this.listUsers
					.getSelectedIndex());

			if (ClientManager.getClientManager().getLogin().equals(guest)
					|| EnumUserStatus.free != ClientManager.getClientManager()
							.getMapUser().get(guest)) {
				this.inviteButton.setEnabled(false);
			} else {
				this.inviteButton.setEnabled(true);
			}

		} else {
			this.inviteButton.setEnabled(false);

		}

	}

	private void updateListUsers() {
		List<String> sortedList = new ArrayList<String>(ClientManager
				.getClientManager().getMapUser().keySet());
		Collections.sort(sortedList);
		int i = this.listUsers.getSelectedIndex();
		String selectedUser = null;
		if (i >= 0) {
			selectedUser = sortedList.get(i);
		}
		this.listUsers.clear();
		for (String user : sortedList) {
			EnumUserStatus status = ClientManager.getClientManager()
					.getMapUser().get(user);

			if (user.equals(ClientManager.getClientManager().getLogin())) {
				this.listUsers.addItem(user, user);
			} else {
				this.listUsers.addItem(user + " (" + status + ")", user);
				if (user.equals(selectedUser)) {
					// preserving the selection before updating.
					this.listUsers.setSelectedIndex(this.listUsers
							.getItemCount() - 1);
				}
			}
		}
	}

}
